-
-
Notifications
You must be signed in to change notification settings - Fork 401
Replace Task.Run wrappers with real asynchronous methods #799
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thank you for your contribution, it is very much appreciated. I will try to review it in the next few days, as there's already another fairly big PR currently in the works. |
e1ae6e1 to
839d61b
Compare
|
Rebased |
|
@virzak The sync-method-generator library is really impressive. It greatly reduces the need to write duplicate code by leveraging the power of However, the author of this project may be hesitant to introduce third-party dependencies. Would it be feasible to extract and adapt a subset of your library's core functionalities, and integrate them into a new project — perhaps named @michelebastione @shps951023 What are your thoughts on introducing third-party dependencies and using |
|
@izanhzh, thank you for the ⭐ and the kind words. Yes, extract whatever you want, it is open source. Crediting and linking the original project in README would be appreciated, if you went that route. This library was made as safe as possible to for integration as a third party as well:
Also, integrating this library with MiniExcel uncovered some compilation errors in earlier versions of the generator, and the generator had to be patched. |
|
@virzak @izanhzh I think this project is really neat, congrats on being a dependency for FluentValidation! That said, and please note this is just my humble opinion, I think source generators in a library should be used only when the code to generate has to reference the consuming applications's assemblies. This would not be the case for this addition. I might be wrong but I believe all the functionalities of a library should be known before it is compiled. But again, this is just my personal take, @shps951023 please let us know your stance. I would also leave in the old async implementation for backwards compatibility and call the new methods something like I hope I don't sound overly critical, I'm just expresing my concerns as this are all very fundamental changes. |
Thanks, @michelebastione! Took a while to convince the maintainer lol.
Now that I gave it more thought, I realized this might be a harder task than it seems.
You'd need to "flatten" all of these in order to even compile sync method generator. Possible, but not sure it is worth it. Also consider what could happen if I believed in this approach and actually flattened UnionTypes library in sync method generator back in 2023. It could diverge from upstream by today and MiniExcel would have to depend on my version of UnionTypes. Not sure if this won't end up being a burden in the long run.
Any time you forgo source generation, you are introducing code duplication. In my opinion (and I'm obviously biased), there is nothing more dangerous in software development that code duplication, which would introduce more work and will be error prone. One solution to "assert control" is to extract public method into an interfaces, which won't be source generated. That way the signature (i.e. the only thing that users are really concerned about) is not source generated.
This is another trade-off. Avoiding breaking change vs following conventions + less methods. Without knowing what is the base of users and how many of them are using the old signatures, I'd say that breaking changes are happening all the time. It usually takes a few minutes to update, so I'd remove it, since I'm unsure how Task<IEnuemerable> could be preferred over IAE or Task<IList>. But there are other options that I like as well. Rather than having: IAsyncEnumerable<T> EnumerateAsync()
Task<IEnumerable<T>> QueryAsync()
IEnumerable<T> Query()You can have: IAsyncEnumerable<T> EnumerateAsync()
Task<IEnumerable<T>> QueryAsync()
IEnumerable<T> Enumerate()
[Obsolete]
IEnumerable<T> Query() //=> redirects to Enumerateor IAsyncEnumerable<T> QueryAsync()
Task<IEnumerable<T>> QueryIEnumerableAsync()
IEnumerable<T> Query()That way at least the sync and async versions are named the same, which is the convention and won't be a surprise to new users of the library.
I tried to leave net45 in place, but was running into compilation issues - so I switched to the latest supported version. I think there is as much merit to support that version as there is to support .NET 7, which this project doesn't support.
Looking forward to seeing it. There is a single (ReadBigExcel_TakeCancel_Throws_TaskCanceledException) test case which passes only 50% of the time. Also looking to see how you tackled other issues, I had struggles with. |
|
All tests are now passing, ready for review. |
|
Before we merge there are still a couple of points I would like to address, nothing major but I believe it's worth talking about it. I'll be writing them down shortly if you have the patience to bear with me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, great job. I was finally going to post my version but it would have been pretty much identical, minus the SyncGenerator stuff of course.
I left a few comments but it's mostly just some missing cancellation tokens.
The only thing left to consider is, and this is more of a question really, if we are dropping support for net45 do we even need to have net462 as an explicit target framework since netstandard2.0 supports it? I suppose that could be problematic with the dependencies to System.IO.Compression and Microsoft.Bcl.AsyncInterfaces, but maybe there's a solution? @shps951023 @izanhzh what do you think?
|
@michelebastione To be honest, if the SyncGenerator can't support net45, removing net45 support would be considered a significant breaking change. This is definitely a tough decision to make. I'm not sure how many people are still using net45, but maintaining both synchronous and asynchronous methods side by side can be quite cumbersome. If we decide to adopt SyncGenerator, this would definitely be a bold attempt. While SyncGenerator provides some convenience, it may also introduce challenges in code maintenance. For example, the generated code might not handle certain special async method calls well. I'm not entirely familiar with the underlying mechanics. I don't have a strong recommendation at this point. Let's see what the @shps951023 has to say about this. |
|
@izanhzh, Sync Method Generator supports net45. However net45 does not support IAsyncEnumerable - at least I was unable to get it to work. |
This comment was marked as resolved.
This comment was marked as resolved.
|
I think that would be a mess of preprocessor instructions and we would still have to define the sync methods from scratch, which goes against the point of including the dependency in the first place. |
This comment was marked as resolved.
This comment was marked as resolved.
|
@michelebastione, thanks for approving! Do I get to Squash and merge it or will someone else do it? |
|
@virzak Given the sheer amount of change this PR brings, I think @shps951023 should give the final word, especially in regards to making this the start of a new major version and subsequent separation of branches like I suggested in my previous comment. |
|
Dear team, We can follow what @michelebastione suggested and upgrade to a new major version. |
|
@michelebastione Leaving squash merging / branching out to you. I'm unsure if this should go to master or a feature branch. |
|
Alright, cool! I created a new branch
I'm writing down a brief commit message and merging shortly. |
|
@virzak Please see the image below. There are a lot of |
|
@izanhzh Currently sync method generator only deals with methods in the same class. Perhaps we can improve this in the future. |

Resolves #529
Resolves #601